#include "xmlWidget.h"
using namespace xmlWidgetLib;



#include <iostream>
#include <string>
using namespace std;

#include "logManager.h"
/*
*******************************************************************************************
*******************************************************************************************
*******************************************************************************************
*******************************************************************************************
*******************************************************************************************
*******************************************************************************************
*******************************************************************************************
*/
const string xmlWidget::m_ScriptPath = "script/";
/*
*******************************************************************************************
*******************************************************************************************
*******************************************************************************************
*******************************************************************************************
*******************************************************************************************
*******************************************************************************************
*******************************************************************************************
*/
xmlWidget::xmlWidget(const char* xmlPath) throw( string * ) 
:m_Widget(NULL)
,m_EmbleWidget(NULL)
,m_hide(false)
,m_RootName("")
,m_XmlRoot(NULL)
,m_Doc(NULL)
,m_ParentWidget(NULL)
,m_level(0)
{
	m_Doc = new TiXmlDocument ;
	TiXmlElement* root;
	logger << __FUNCTION__ << " Start" << endl;

	if( false == m_Doc->LoadFile(xmlPath) )
	{
		string throwMsg("Error: can not open file [");
		throwMsg += string(xmlPath) + "]";
		throw new string(throwMsg);
	}
	root = m_Doc->RootElement();
	string rootName( root->Value());
	if( "Widget" != rootName )
	{
		throw new string("Error: can not get widget root element");
	}
	m_XmlRoot = root;
	try
	{
		this->parseXmlRoot();
	}
	catch( string * msg )
	{
		throw msg;
	}
	logger << __FUNCTION__ << " Success" << endl;
}


xmlWidget::xmlWidget( TiXmlElement* xmlElement ,xmlWidget *parent ) throw( string * )
:m_Widget(NULL)
,m_EmbleWidget(NULL)
,m_hide(false)
,m_RootName("")
,m_XmlRoot(xmlElement)
,m_Doc(NULL)
,m_ParentWidget(parent)
,m_level(0)
{
	logger << __FUNCTION__ << " Start" << endl;
	m_level = m_ParentWidget-> m_level + 1 ;

	if( NULL == m_XmlRoot )
	{
		throw new string("Error: invlad xml element");
	}
	try
	{
		this->parseXmlRoot();
	}
	catch( string * msg )
	{
		throw msg;
	}
	logger << __FUNCTION__ << " Success" << endl;
}

xmlWidget::~xmlWidget()
{
	if(m_Doc)
	{
		delete m_Doc;
	}
}



void xmlWidget::parseXmlRoot(void) throw( string * )
{
	logger << __FUNCTION__ << " Start" << endl;
	const char *name = m_XmlRoot->Attribute("name");
	if( NULL == name )
	{
		throw new string("Error: can not get widget name");			
	}
	m_RootName = name;
	if( m_ParentWidget )
	{
		string key(name);
		m_ParentWidget->m_SubWidgets[key] = this;
	}

	const char *hidden = m_XmlRoot->Attribute("StartHidden");
	if( hidden )
	{
		if( "true" == string(hidden) )
		{
			m_hide = true;
		}
	}

	const char *type = m_XmlRoot->Attribute("type");
	if( NULL == type )
	{
		throw new string("Error: can not get widget type");			
	}
	try
	{
		string typeStr(type);
		if( "MainWindow" == typeStr )
		{
			this->parseXmlMainWindow();
		}
		if( "subWindow" == typeStr )
		{
			this->parseXmlSubWindow();
		}
		if( "MainMenu" == typeStr )
		{
			this->parseXmlMainMenu();
		}
		if( "PopMenu" == typeStr )
		{
			this->parseXmlPopMenu();
		}
		if( "Menu" == typeStr )
		{
			this->parseXmlMenu();
		}
		if( "MenuItem" == typeStr )
		{
			this->parseXmlMenuItem();
		}
		if( "FileSelection" == typeStr )
		{
			this->parseXmlFileSelection();
		}
	}
	catch( string * msg )
	{
		throw msg;
	}

	try
	{
		this->parseXmlChildWidget();
		this->parseXmlAction();
	}
	catch( string * msg )
	{
		throw msg;
	}
	logger << __FUNCTION__ << " Success" << endl;
}

void xmlWidget::parseXmlChildWidget(void) throw( string * )
{
	logger << __FUNCTION__ << " Start" << endl;
	TiXmlNode *first = m_XmlRoot->FirstChild("Widget");
	TiXmlNode *last = m_XmlRoot->LastChild("Widget");
	TiXmlNode *pre = first;
	TiXmlNode *ir = first;
//	logger << "try to find child widget" << endl;
	try
	{
		while( NULL != ir)
		{
			TiXmlElement *childElement = ir->ToElement();
//			logger << "find a child widget" << endl;
			xmlWidget *childWidget = new xmlWidget(childElement,this);

			// continue next child 
			ir = m_XmlRoot->IterateChildren("Widget",pre);
			pre = ir;
		}
	}
	catch( string * msg )
	{
		throw msg;
	}
	logger << __FUNCTION__ << " Success" << endl;
}





void xmlWidget::parseXmlAction(void) throw( string * )
{
	logger << __FUNCTION__ << " Start" << endl;
	TiXmlNode *first = m_XmlRoot->FirstChild("Action");
	TiXmlNode *last = m_XmlRoot->LastChild("Action");
	TiXmlNode *pre = first;
	TiXmlNode *ir = first;
	try
	{
		while( NULL != ir)
		{
			TiXmlElement *childElement = ir->ToElement();
//			logger << "find a child widget" << endl;
			const char *type = childElement->Attribute("name");
			if( NULL == type )
			{
				throw new string("Error: can not get widget type");			
			}
			else
			{
				string key(type);
				const char * actions = childElement->GetText();
				string actString(actions);
				m_Actions[type] = m_ScriptPath + actString;
			}

			// continue next child 
			ir = m_XmlRoot->IterateChildren("Action",pre);
			pre = ir;
		}
	}
	catch( string * msg )
	{
		throw msg;
	}
	logger << __FUNCTION__ << " Success" << endl;
}


void xmlWidget::show(void)
{
	logger << __FUNCTION__ << " " << m_RootName << endl;
	if( m_Widget && false == m_hide )
	{
		logger << __FUNCTION__ << " " << m_RootName << endl;
		gtk_widget_show(m_Widget);
	}
	if( m_EmbleWidget && false == m_hide )
	{
		gtk_widget_show(m_EmbleWidget);
	}
	xmlWidgetMap::const_iterator it = m_SubWidgets.begin();
	for( ; m_SubWidgets.end() != it ; it++ )
	{
		it->second->show();
	}
}

void xmlWidget::hide(void)
{
	logger << __FUNCTION__ << " " << m_RootName << endl;
	if( m_Widget )
	{
		logger << __FUNCTION__ << " " << m_RootName << endl;
		gtk_widget_hide(m_Widget);
	}
	if( m_EmbleWidget )
	{
		gtk_widget_hide(m_EmbleWidget);
	}
	xmlWidgetMap::const_iterator it = m_SubWidgets.begin();
	for( ; m_SubWidgets.end() != it ; it++ )
	{
		it->second->hide();
	}
}

void xmlWidget::dumpTree( void )
{
	if( NULL == m_ParentWidget )
	{
		logger << __FUNCTION__ << "\t" << m_RootName << endl;
	}

	string level = "\t\t|" ;
	for( int i = 0;i <= m_level ; i++ )
	{
		level += "\t|";
	}
	xmlWidgetMap::const_iterator it = m_SubWidgets.begin();
	for( ; m_SubWidgets.end() != it ; it++ )
	{
		logger << __FUNCTION__ << level << it->first << endl;
		it->second->dumpTree();
	}
}
void xmlWidget::dumpInfo( const string & info )
{
	logger << __FUNCTION__ << "\t" << m_RootName << "\t" << info << endl;
}

xmlWidget* xmlWidget::search( const string &key )
{
// compare itself
	if( key == m_RootName )
	{
		return this;
	}
// compare sub widgets
	xmlWidgetMap::const_iterator it = m_SubWidgets.find(key);
	if( m_SubWidgets.end() != it )
	{
		return it->second ;
	}
// search in sub widgets
	it = m_SubWidgets.begin();
	for( ; m_SubWidgets.end() != it ; it++ )
	{
		xmlWidget* pTemp = it->second->search(key);
		if(pTemp)
		{
			return pTemp;
		}
	}
// no hit
	return NULL;
}
